package com.icbc.cc.api;

import java.util.Iterator;

import org.apache.commons.codec.binary.Base64;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.icbc.cc.security.app.AppAESUtil;
import com.icbc.cc.security.app.AppDSAUtil;
import com.icbc.cte.base.CTEConstance;
import com.icbc.cte.logging.Log;
import com.icbc.cte.logging.LogFactory;
import com.icbc.ctp.core.IContext;
import com.icbc.ctp.core.factory.OpAssemblyFactory;
import com.icbc.ctp.core.impl.Context;
import com.icbc.ctp.core.impl.Operation;
import com.icbc.ctp.ioc.ConstructorException;
import com.icbc.ctp.ioc.FactortInitialException;
import com.icbc.ctp.ioc.ModulesException;
import com.icbc.ctp.ioc.xmlconfig.FileSystemXmlApplicationContext;
import com.szkingdom.kwis.common.security.DESEncrypt;


public class ApiCommonUtils {
	private static String APP_AES_KEY = CTEConstance
			.getEnvProperty("appServerAesKey");
	private static String APP_DSA_PUB_KEY = CTEConstance
			.getEnvProperty("appDsaPubKey");
	private static String SERVER_DSA_PRI_KEY = CTEConstance
			.getEnvProperty("serverDsaPriKey");

	public static String APP_CALL_FLAG = "0";
	public static String API_CALL_FLAG = "1";

	private static Log log = LogFactory.getCtpLog(ApiCommonUtils.class);
	
	/**
	 * TODO 方法的描述：执行opg，查询结果数据。
	 * 
	 * @param param
	 *            ：输入参数
	 * @param opName
	 *            ：opg名称
	 * @return JSON结果集的String形式
	 */
	public static String excuteOp(String param, String opName) {

		log.info("ApiCommonUtils.excuteOp param:" + param);
		log.info("ApiCommonUtils.excuteOp opName:" + opName);
		
		FileSystemXmlApplicationContext appCtx = FileSystemXmlApplicationContext
				.getFactory();
		OpAssemblyFactory opFactory;
		Operation op = null;
		IContext ctx = new Context();

		JSONObject paramJson = (JSONObject) JSONObject.parse(param);//使用fastjson处理请求传入的json数据param
		JSONObject resultJson = new JSONObject();//定义准备返回的json数据

		// 返回结果中，去掉下列key值
		String exceptKeys = "_CONTAINER_TMP_HOUSE|_clientIP|_asynDebugId|_flowActionStack|"
				+ "_op_start_time|_transFlag|_transactionId|stateCode";

		try {
			opFactory = (OpAssemblyFactory) appCtx
					.getModule("operationFactory");

			op = opFactory.createOperation(opName);

			// 如果是注册、登录、重置密码等接口，则将登录密码进行加密
			if ("user_regist".equals(opName) || "user_login".equals(opName)
					|| "reset_password".equals(opName)
					|| "update_regist_mobile".equals(opName)
					|| "update_bank_mobile".equals(opName)
					|| "validate_password".equals(opName)) {
				
				String password = paramJson.getString("password") == null ? "" : DESEncrypt.strEnc(paramJson.getString("password"));
				paramJson.put("password", password);

			} else if ("update_password".equals(opName)) {
				
				String oldPwd = paramJson.getString("oldPwd") == null ? "" : DESEncrypt.strEnc(paramJson.getString("oldPwd"));
				paramJson.put("oldPwd", oldPwd);
				
				String newPwd = paramJson.getString("newPwd") == null ? "" : DESEncrypt.strEnc(paramJson.getString("newPwd"));
				paramJson.put("newPwd", newPwd);

			}else if ("update_sign_password".equals(opName)) {
				String signPwd = paramJson.getString("signPwd") == null ? "" : DESEncrypt.strEnc(paramJson.getString("signPwd"));
				paramJson.put("signPwd", signPwd);
			}else if ("user_sign_login".equals(opName)) {
				String signPwd = paramJson.getString("signPwd") == null ? "" : DESEncrypt.strEnc(paramJson.getString("signPwd"));
				paramJson.put("signPwd", signPwd);
			}
				
			/**
			 * 将param解析为单独的一个个键值对，然后分别放入到Context域中
			 */
			if (paramJson != null && !paramJson.isEmpty()) {
				for (String key : paramJson.keySet()) {
					ctx.setValueAt(key, paramJson.get(key));
				}
			}

			op.doExecute(ctx);

			for (String key : ctx.keySet()) {
				if (!exceptKeys.contains(key)) {//需要排除的Key里面包含这个key就不执行，不需要排除的key里面有这个key才执行
					Object value = ctx.getValueAt(key);
					if (value == null) {//对根据键取到的值做一个空值判断
						value = "";
					}
					resultJson.put(key, value);//证明response中是需要这个参数和值，放入resultJson
				}
			}
			
			
			
		} catch (ModulesException e) {
			e.printStackTrace();
			log.error(e.getCause());
		} catch (FactortInitialException e) {
			e.printStackTrace();
			log.error(e.getCause());
		} catch (ConstructorException e) {
			e.printStackTrace();
			log.error(e.getCause());
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getCause());
		}

		log.info("ApiCommonUtils.excuteOp resultJson:" + resultJson.toJSONString());
		
		return resultJson.toJSONString();

	}
	
	/**
	 * TODO 方法的描述：校验验证码
	 * 
	 * @param param
	 *            ：输入参数
	 * @return JSON结果集的String形式
	 */
	public static String excuteOpCheck(String param,String checkCode) {

		log.info("ApiCommonUtils.excuteOp param:" + param);

		JSONObject paramJson = (JSONObject) JSONObject.parse(param);//使用fastjson处理请求传入的json数据param
		JSONObject resultJson = new JSONObject();//定义准备返回的json数据

		try {
			String verifyCode=paramJson.get("verifyCode").toString();
			if(!verifyCode.equals(checkCode)){
				resultJson.put("retCode", "-1");
				resultJson.put("retMsg", "验证码输入错误");
			}else{
				resultJson.put("mobileNo", paramJson.get("mobileNo").toString());
				resultJson.put("retCode", "0");
				resultJson.put("retMsg", "验证码输入正确");
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getCause());
		}

		log.info("ApiCommonUtils.excuteOp resultJson:" + resultJson.toJSONString());
		
		return resultJson.toJSONString();

	}
	
	/**
	 * TODO 方法的描述：AES加密与生成数字签名。
	 * 
	 * @param param
	 * @return
	 */
	public static String encrypAndSign(String data, String osFlag) {
		JSONObject obj = new JSONObject();
		//IOS
		if ("1".equals(osFlag)) {
			return encrypAndSignIos(data);
		//PC
		} else if ("3".equals(osFlag)) {
			return encrypAndSignJsp(data);
		//微信	
		}else if("4".equals(osFlag)){
		
		//安卓	
		}else if("2".equals(osFlag)){
			
			if (data != null && data.length() > 0) {
				try {
					String aesData = AppAESUtil.encrypt(data, APP_AES_KEY);
					String sign = AppDSAUtil.sign(aesData.getBytes(),
							SERVER_DSA_PRI_KEY);
					obj.put("data2", aesData);
					obj.put("data1", sign);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}else if("5".equals(osFlag)){
			return encrypAndSignHTML5(data);
		}
		
		return obj.toString();
		
	}
	
	public static String encrypAndSignHTML5(String data) {

		String ret = "";
		if (data != null && data.length() > 0) {
			try {
				JSONObject json = JSONObject.parseObject(data);
				String retMsg = json.getString("retMsg");
//				if (retMsg != null && retMsg.length() > 0 ) {
//					json.put("retMsg", java.net.URLEncoder.encode(retMsg, "UTF-8"));
//				}

				//BASE64Encoder encoder = new BASE64Encoder();
//				String str=new String(json.toJSONString().getBytes("UTF-8"),"UTF-8");
//				String str=json.toJSONString();
//				byte[]b=Base64.encodeBase64URLSafe(str.getBytes("UTF-8"));
//				ret=new String(b,"UTF-8");
				ret = Base64.encodeBase64URLSafeString(json.toJSONString().getBytes("UTF-8"));
				//ret = encoder.encode(json.toJSONString().getBytes());
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return ret;
	}
	
	public static String encrypAndSignJsp(String data) {

		String ret = "";
		if (data != null && data.length() > 0) {
			try {
				JSONObject json = JSONObject.parseObject(data);
				String retMsg = json.getString("retMsg");
				if (retMsg != null && retMsg.length() > 0 ) {
					json.put("retMsg", java.net.URLEncoder.encode(retMsg, "UTF-8"));
				}

				//BASE64Encoder encoder = new BASE64Encoder();
//				String str=new String(json.toJSONString().getBytes("UTF-8"),"UTF-8");
				String str=json.toJSONString();
				byte[]b=Base64.encodeBase64URLSafe(str.getBytes("UTF-8"));
				ret=new String(b,"UTF-8");
				//ret = encoder.encode(json.toJSONString().getBytes());
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return ret;
	}
	
	public static String encrypAndSign1(String data) {
		JSONObject obj = new JSONObject();
		if (data != null && data.length() > 0) {
			try {
				String aesData = AppAESUtil.encrypt(data, APP_AES_KEY);
				//String sign = AppDSAUtil.sign(aesData.getBytes(),
				//		SERVER_DSA_PRI_KEY);
				obj.put("data2", aesData);
				//obj.put("data1", sign);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return obj.toString();
	}

	/**
	 * 
	 * TODO 方法的描述：AES解密与校验数字签名。
	 * 
	 * @param param
	 * @return
	 */
	public static String decrypAndSign(String data, String callFlag, String osFlag) {
		String retData = null;
		//判断是pc端还是ios端
		if ("1".equals(osFlag)) {//iOS端
			retData=decrypAndSignIos(data, callFlag);
			log.info("ApiCommonUtils.decrypAndSign param:" + retData);
			//return decrypAndSignIos(data, callFlag);
			return retData;
		} else if ("3".equals(osFlag)) {//pc端
			retData=decrypAndSignJsp(data);
			log.info("ApiCommonUtils.decrypAndSign param:" + retData);
			//return decrypAndSignJsp(data);
			return retData;
		}else if("4".equals(osFlag)){
			
		//安卓	
		}else if("2".equals(osFlag)){
			if (data != null && data.length() > 0) {
				JSONObject objData = (JSONObject) JSONObject.parse(data);
				String aesData = (String) objData.get("data2");
				String sign = (String) objData.get("data1");
				try {
					if (AppDSAUtil
							.verify(aesData.getBytes(), APP_DSA_PUB_KEY, sign)) {
						if (aesData != null && aesData.length() > 0) {
							retData = AppAESUtil.decrypt(aesData, APP_AES_KEY);
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}else if ("5".equals(osFlag)) {//pc端
			retData=decrypAndSignJsp(data);
			log.info("ApiCommonUtils.decrypAndSign param:" + retData);
			//return decrypAndSignJsp(data);
			return retData;
		}
		log.info("ApiCommonUtils.decrypAndSign param:" + retData);
		return retData;
	}
	
	/**
	 * jsp页面
	 * 
	 * @param param
	 * @return
	 */
	public static String decrypAndSignJsp(String data) {

		if (data != null && data.length() > 0) {

			try {
				BASE64Decoder decorder = new BASE64Decoder();
				//byte[] d = decorder.decodeBuffer(data);
				byte[] d=Base64.decodeBase64(data);
				return new String(d,"UTF-8");
				
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return "";
	}

	public static String decrypAndSign1(String data, String callFlag) {
		String retData = null;
		if (data != null && data.length() > 0) {
			JSONObject objData = (JSONObject) JSONObject.parse(data);
			String aesData = (String) objData.get("data2");
			String sign = (String) objData.get("data1");
			try {
				//if (AppDSAUtil
				//		.verify(aesData.getBytes(), APP_DSA_PUB_KEY, sign)) {
					if (aesData != null && aesData.length() > 0) {
						retData = AppAESUtil.decrypt(aesData, APP_AES_KEY);
					}
				//}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return retData;
	}

	/**
	 * 方法的描述：AES加密与生成数字签名。
	 * 
	 * @param param
	 * @return
	 */
	public static String encrypAndSignIos(String data) {
		JSONObject obj = new JSONObject();
		if (data != null && data.length() > 0) {
			try {
				String aesData = IOSSecurityUtil.encrypt(data);
				String sign = IOSSecurityUtil.sign(aesData);
				obj.put("data2", aesData);
				obj.put("data1", sign);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return obj.toString();
	}

	/**
	 * 
	 * 方法的描述：AES解密与校验数字签名。
	 * 
	 * @param param
	 * @return
	 */
	public static String decrypAndSignIos(String data, String callFlag) {
		String retData = null;
		if (data != null && data.length() > 0) {
			JSONObject objData = (JSONObject) JSONObject.parse(data);
			String aesData = (String) objData.get("data2");//data2是经过aes加密过的数据
			String sign = (String) objData.get("data1");//data1是数据签名
			try {
				if (IOSSecurityUtil.verify(aesData, sign)) {
					if (aesData != null && aesData.length() > 0) {
						retData = IOSSecurityUtil.decrypt(aesData);
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return retData;
	}
	
	// 解析第三方接口返回的数据
	public static String parseRemsgFromApi(String remsg) {
		JSONObject retObj = new JSONObject();
		JSONObject objResmg = (JSONObject) JSONObject.parse(remsg);

		String retCode = objResmg.getString("code");
		String strRespData = objResmg.getString("respData");

		// 调用接口成功
		if ("0000".equals(retCode)) {
			JSONArray objRespData = (JSONArray) JSONObject.parse(strRespData);
			Iterator<Object> iterator = ((JSONArray) objRespData.get(0))
					.iterator();
			retObj = (JSONObject) iterator.next();
			retObj.put("retCode", "0");
			retObj.put("retMsg", "调用接口成功");
		} else {
			retObj.put("retCode", "-1");
			retObj.put("retMsg", strRespData);
		}
		System.out.println(retObj.toString());
		return retObj.toString();
	}

	// 从身份证号截取生日
	public static String getBirthDayFromIDcard(String IDCardNo) {
		String birthDay = null;
		if (IDCardNo != null) {
			birthDay = IDCardNo.substring(6, 14);
		}
		return birthDay;

	}

	// 从身份证号截取性别
	public static String getGenderFromIDcard(String IDCardNo) {
		String gender = null;
		if (IDCardNo != null) {
			gender = IDCardNo.substring(IDCardNo.length() - 2,
					IDCardNo.length() - 1);
		}
		// 身份证倒数第二位：1-男2-女；第三方接口;0-女1-男
		if ("2".equals(gender)) {
			gender = "0";
		}
		return gender;

	}

	/**
	 * 
	 * 短信记录 
	 * <pre>
	 *
	 * </pre>
	 * @param prdId 产品代码
	 * @param msgType 提示类型(1.私募下单 2.短信广告)
	 * @param sendObject 发送对象(1.销售渠道 2.APP用户)
	 * @param sendMobile 对象手机号
	 * @param sendCont 内容
	 * @param sendSuccess 是否送达(1.是 0.否)
	 * @param prdFlag 产品区分(1.公募 2.私募)
	 * @return
	 */
	public static String addMsgSmsLog(String prdId, String msgType,
			String sendObject, String sendMobile,
			String sendCont, String sendSuccess, String prdFlag) {

		JSONObject param = new JSONObject();
		
		param.put("prdId", prdId);
		param.put("msgType", msgType);
		param.put("sendObject", sendObject);
		param.put("sendMobile", sendMobile);
		param.put("sendCont", sendCont);
		param.put("sendSuccess", sendSuccess);
		param.put("prdFlag", prdFlag);

		String ret = ApiCommonUtils.excuteOp(param.toJSONString(), "addmsgsmslog");
		
		return ret;
	}
	
	/**
	 * 
	 * 从byte数组中取得图片的扩展名 
	 * <pre>
	 *
	 * </pre>
	 * @param b
	 * @return
	 */
	public static String getImageExtension(byte[] b) {
		
		String ext = ".jpg";
		
		if (b.length == 0) {
			return ext;
		}
		
		byte[] array = new byte[2];
		array[0] = b[0];
		array[1] = b[1];
		
		String header = bytesToHexString(array);
		
		if (header.startsWith("8950")) {
			ext = ".png";
		} else if (header.startsWith("ffd8")) {
			ext = ".jpg";
		} else if (header.startsWith("424d")) {
			ext = ".bmp";
		}
		
		return ext;
	}
	
	/**
	 * 
	 * byte数组转换成16进制字符串
	 * <pre>
	 *
	 * </pre>
	 * @param src
	 * @return
	 */
	public static String bytesToHexString(byte[] src){  
	    StringBuilder stringBuilder = new StringBuilder("");  
	    if (src == null || src.length <= 0) {  
	        return null;  
	    }  
	    for (int i = 0; i < src.length; i++) {  
	        int v = src[i] & 0xFF;  
	        String hv = Integer.toHexString(v);  
	        if (hv.length() < 2) {  
	            stringBuilder.append(0);  
	        }  
	        stringBuilder.append(hv);  
	    }
	    return stringBuilder.toString();  
	}
}
